#ifndef TEMPLE_UTIL_STDCC_H_
#define TEMPLE_UTIL_STDCC_H_

#include "stdc.h"
namespace util{

template<class T>
class Number
{
public:
	Number()
	{
		num = 0;
	}

	Number(const T &val)
	{
		num = val;
	}

	Number(const Number &other)
	{
		num = other.num;
	}

	Number(Number &&other)
	{
		num = other.num;
	}

	Number &operator=(const T &val)
	{
		num = val;
		return *this;
	}

	Number &operator=(const Number &other)
	{
		num = other.num;
		return *this;
	}

	Number &operator=(Number &&other)
	{
		num = other.num;
		return *this;
	}

	Number &operator+=(const T &val)
	{
		num += val;
		return *this;
	}

	Number &operator+=(const Number &other)
	{
		num += other.num;
		return *this;
	}

	Number operator+(const T &val) const
	{
		Number tmp;
		tmp = num + val;
		return tmp;
	}

	Number operator+(const Number &other) const
	{
		Number tmp;
		tmp = num + other.num;
		return tmp;
	}

	bool operator>(const T &val) const
	{
		return num > val;
	}

	bool operator>(const Number &other) const
	{
		return num > other.num;
	}

	friend inline bool operator>(const T &val, const Number &other)
	{
        return val > other.num;
    }

	bool operator>=(const T &val) const
	{
		return num >= val;
	}

	bool operator>=(const Number &other) const
	{
		return num >= other.num;
	}

	friend inline bool operator>=(const T &val, const Number &other)
	{
        return val >= other.num;
    }

	bool operator<(T val) const
	{
		return num < val;
	}

	bool operator<(const Number &other) const
	{
		return num < other.num;
	}

	friend inline bool operator<(const T &val, const Number &other)
	{
        return val < other.num;
    }

	bool operator<=(const T &val) const
	{
		return num <= val;
	}

	bool operator<=(const Number &other) const
	{
		return num <= other.num;
	}

	friend inline bool operator<=(const T &val, const Number &other)
	{
        return val <= other.num;
    }

	bool operator!=(const T &val) const
	{
		return num != val;
	}

	bool operator!=(const Number &other) const
	{
		return num != other.num;
	}

	friend inline bool operator!=(const T &val, const Number &other)
	{
        return val != other.num;
    }

	operator T() const
	{
		return num;
	}

	T c_num() const
	{
		return num;
	}

private:
	T num;
};

class strref
{
public:
	inline strref()
	{
		str = nullptr;
		len = 0;
	}

	inline strref(const strref &other)
	{
		str = new char[other.len+1];
		len = other.len;
		memcpy(str, other.str, len);
		str[len] = '\0';
	}

	inline strref(strref &&other)
	{
		str = other.str;
		len = other.len;
		other.str = nullptr;
		other.len = 0;
	}

	inline strref(const char *s, size_t n)
	{
		str = new char[n+1];
		len = n;
		memcpy(str, s, len);
		str[len] = '\0';
	}

	inline strref(char *&&s, size_t n)
	{
		str = s;
		len = n;
		s = nullptr;
	}

	inline ~strref()
	{
	    delete[] str;
	}

	inline strref &operator=(const strref &other)
	{
	    delete[] str;
		str = new char[other.len+1];
		len = other.len;
		memcpy(str, other.str, len);
		str[len] = '\0';
		return *this;
	}

	inline strref &operator=(strref &&other)
	{
		str = other.str;
		len = other.len;
		other.str = nullptr;
		other.len = 0;
		return *this;
	}

	inline void assign(const char *s, size_t n)
	{
	    delete[] str;
		str = new char[n+1];
		len = n;
		memcpy(str, s, len);
		str[len] = '\0';
	}

	inline void assign(char *&&s, size_t n)
	{
	    delete[] str;
		str = s;
		len = n;
		s = nullptr;
	}

	inline const char *c_str() const
	{
	    return str;
	}

	inline bool empty() const
	{
		return len==0;
	}

	inline size_t length() const
	{
		return len;
	}

	inline std::string to_str() const
	{
		return std::string(str, len);
	}

	std::string substr(size_t pos, size_t len)
	{
		if (pos >= len)
			return std::string();

		return std::string(str+pos, len-pos>=len ? len : len-pos);
	}

	bool operator==(const char *str) const
	{
		if (len != strlen(str))
			return false;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != str[i])
				return false;
		}

		return true;
	}

	bool operator==(const std::string &str) const
	{
		if (len != str.length())
			return false;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != str[i])
				return false;
		}

		return true;
	}

	bool operator==(const strref &other) const
	{
		if (len != other.len)
			return false;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != other.str[i])
				return false;
		}

		return true;
	}

	bool operator!=(const char *str) const
	{
		if (len != strlen(str))
			return true;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != str[i])
				return true;
		}

		return false;
	}

	bool operator!=(const std::string &str) const
	{
		if (len != str.length())
			return true;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != str[i])
				return true;
		}

		return false;
	}

	bool operator!=(const strref &other) const
	{
		if (len != other.len)
			return true;

		for (size_t i=0; i<len; ++i)
		{
			if (str[i] != other.str[i])
				return true;
		}

		return false;
	}

private:
	char *str;
	size_t len;
};

}

typedef util::Number<i64> int64;
typedef util::Number<i32> int32;
typedef util::Number<i16> int16;

typedef util::Number<u64> uint64;
typedef util::Number<u32> uint32;
typedef util::Number<u16> uint16;

typedef std::string string;
typedef util::strref strref;

#endif //TEMPLE_UTIL_STDCC_H_
